{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## <center> Индивидуальный проект по анализу данных "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## <center> Прогнозирование успешности проекта на Kickstarter\n",
    "##### <center> Автор материала: Никита Большагин (@nikitab)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###  Часть 1. Описание набора данных и признаков"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "**_Краудфандинг_** (aka народное финансирование, от англ. _crowd_ - толпа, _funding_ - финансирование) – это, грубо говоря, когда некоторая группа людей добровольно «скидывается» (чаще всего деньгами) для того, чтобы поддержать усилия других людей или организаций. Само явление сбора средств народными массами известно достаточно давно. К примеру, создание Статуи Свободы и постройка пьедестала для нее финансировались за счет добровольных пожертвований. Продвижением краудфандинговой кампании для сбора средств на строительство пьедестала для статуи в Америке, занимался известный журналист Джозеф Пулитцер. Также можно вспомнить знаменитый долгострой Саграда Фамилия в Барселоне (строительство финансируется только за счет пожертвований), памятник Минину и Пожарскому (скинулись всей «благодарной Россией»), Храм Христа Спасителя (частично за счет пожертвований). \n",
    "\n",
    "Первым примером интернет-краудфандинга является сбор средств на организацию гастрольного тура по США британской рок-группы Marillion (1997 год). Причем сама группа тут не при чем. Постарались поклонники, которые скинулись с миру по нитке и собрали 60000$. Позже, смекалистая рок-банда использовала такой способ сбора средств для финансирования своих новых альбомов. В 2001 году появляется первая краудфандинговая платформа для музыкантов ArtistShare. В след за ней появляются площадки для кино (FilmVenture.com) и пошло поехало – Sellaband (2006), SliceThePie (2007), IndieGoGo (2008), KickStarter(2009) и др. В России  краудфандинговые интернет площадки появляются чуть позже в 2012 году – Planeta.ru и Boomstarter. \n",
    "\n",
    "Сам краудфандинг можно разделить на три категории – _отсутствие вознаграждения_ (характерно для благотворительности, например, когда объявляется сбор средств на лечение заболевания); _финансовое вознаграждение_ (краудинвестинг – в этом случае спонсор становится инвестором, и он уже получает какую-то финансовую выгоду в обмен на свою поддержку); _нефинансовое вознаграждение_ (на такой системе построен Кикстартер – спонсоры получают различные награды в зависимости от размера пожертвования). \n",
    "\n",
    "На Кикстартере и остановимся. Проект появился в 2009 году и его девизом стало «помочь воплотить в жизнь творческие проекты». Модель платформы заключается в следующем – автор проекта должен указать срок и минимальную сумму, которую необходимо собрать, чтобы проект мог быть реализован. Если проект не собирает нужную сумму к указанному сроку, то все деньги возвращаются спонсорам. \n",
    "\n",
    "Естественно, было бы полезным узнать заранее, будет ли проект успешным. Данные для индивидуального проекта взяты из этого [датасета](https://www.kaggle.com/kemical/kickstarter-projects). Данные собраны на конец января 2018 г. \n",
    "\n",
    "Описание признаков следующее:\n",
    " - **ID** - идентификатор проекта, целочисленный\n",
    " - **name** - название проекта, строковый\n",
    " - **category** - подкатегория проекта, категориальный \n",
    " - **main_category** - категория проекта, категориальный\n",
    " - **currency** - валюта, в которой собираются пожертвования, категориальный\n",
    " - **deadline** - дата, к которой нужно собрать запрашиваемую сумму\n",
    " - **goal** - запрашиваемая сумма денег (в валюте проекта), вещественный\n",
    " - **launched** - дата запуска сбора средств\n",
    " - **pledged** - сумма пожертвований (в валюте проекта), вещественный\n",
    " - **state** - итог компании сбора средств, категориальный\n",
    " - **backers** - количество людей, сделавших пожертвование, целочисленный\n",
    " - **country** - страна проекта, категориальный\n",
    " - **usd_pledged** - сумма пожертвований в долларах (конвертация кикстартера), вещественный\n",
    " - **usd_pledged_real** - сумма пожертвований в долларах (конвертация по курсу на день\n",
    "   закрытия сбора средств), вещественный\n",
    " - **usd_goal_real** - запрашиваемая сумма денег в долларах, вещественный\n",
    "\n",
    "Основная цель - это определить будет ли успешным проект или он провалится. Для того, чтобы это определить, в данных есть два признака - **state** и **usd_pledged_real**.\n",
    "\n",
    "Признак **state** (6 уникальных значений): \n",
    " - *failed* - проект провалился\n",
    " - *successful* - проект успешен\n",
    " - *canceled* - проект был закрыт инициатором\n",
    " - *suspended* - проект был приостановлен модераторами кикстартера\n",
    " - *live* - проект до сих пор собирает средства\n",
    " - *undefined* - состояние проекта не определено (скорее всего какие-то ошибки при парсинге)\n",
    " \n",
    "Предсказать, что проект может быть закрыт инициатором проекта или приостановлен командой модераторов может быть довольно нетривиальной задачей, для решения которой, скорее всего, необходимо больше данных - например, как-нибудь оценивать качество описание проекта (смотреть количество картинок и видео на странице проекта). \n",
    "\n",
    "С признаком **usd_pledged_real** в качестве целевой переменной будет немного проще. Нам просто необходимо, чтобы количество полученных денег к концу дедлайна было больше, чем запрошено при запуске проекта. Тогда проект можно будет считать успешным :) \n",
    "\n",
    "Для **целевой переменной** я выбрал признак **state**. Будет решаться задача бинарной классификации (**failed** или **successul**). \n",
    "\n",
    "*Ремарка*: признаки **usd_pledged_real** и **usd_goal_real** получены путем конвертации значений признаков **pledged** и **goal** с помощью стороннего [сервиса](https://fixer.io/)). Автор датасета утверждает, что конвертация валют самим Кикстартером несет в себе некоторые неточности.\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Импорт необходимых библиотек"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "\n",
    "import seaborn as sns\n",
    "import matplotlib.pyplot as plt\n",
    "plt.style.use('classic')\n",
    "%matplotlib inline\n",
    "\n",
    "from sklearn.linear_model import LogisticRegression\n",
    "from sklearn.metrics import roc_auc_score\n",
    "from sklearn.preprocessing import StandardScaler, LabelEncoder, OneHotEncoder\n",
    "from sklearn.ensemble import RandomForestClassifier\n",
    "from sklearn import model_selection\n",
    "from sklearn.model_selection import train_test_split, TimeSeriesSplit, GridSearchCV\n",
    "from sklearn.learning_curve import learning_curve\n",
    "\n",
    "import warnings\n",
    "warnings.filterwarnings('ignore')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###  Часть 2. Первичный анализ признаков"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Загрузим данные и посмотрим информацию по ним"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data = pd.read_csv('..\\data\\ks-projects-201801.csv')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data.info()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Видно, что признак **usd_pledged** отсутствует у некоторых проектов. Т.к. он дублирует признак **usd_pledged_real**, выкинем **usd_pledged**.\n",
    "Так же можно заметить, что у 4 проектов не заполнено поле **name**. Их мы тоже выбросим из исходного датасета. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data.isna().sum()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data.drop('usd pledged', axis=1, inplace=True)\n",
    "data.dropna(inplace=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Оценим долю проектов которые по какой-то причине были закрыты или приостановлены, так же посмотрим на проекты которые собирают средства."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "canceled_projects = len(data[data['state'] == 'canceled'])\n",
    "suspend_projects = len(data[data['state'] == 'suspended'])\n",
    "undefined_projects = len(data[data['state'] == 'undefined']) \n",
    "live_projects = len(data[data['state'] == 'live'])\n",
    "total = len(data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('Доля закрытых проектов: ', 100 * canceled_projects/total)\n",
    "print('Доля приостановленных проектов: ', 100 * suspend_projects/total)\n",
    "print('Доля неопределенных проектов: ', 100 * undefined_projects/total)\n",
    "print('Доля открытых проектов: ', 100 * live_projects/total)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Чуть больше 10% процентов проектов закрыты авторами, это достаточно существенная часть от общего количества данных. Но т.к. поставлена задача оценить провал/успех проекта, скрепя сердце, выбросим эти данные.  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data.drop(data[(data['state'] == 'canceled') | (data['state'] == 'live') | (data['state'] == 'suspended') | (data['state'] == 'undefined')].index, inplace=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Посмотрим на числовые признаки*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "num = ['goal', 'pledged', 'backers', 'usd_goal_real', 'usd_pledged_real']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure(figsize=(8, 5))\n",
    "sns.set(font_scale=1.2)\n",
    "sns.heatmap(data[num].corr(), cmap='viridis', annot=True, linewidths=.5);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Очевидна корелляция между **goal** и **usd_goal_real**, **pledged** и **usd_pledged_real**. Заметно, что итоговая сумма пожертвований сильно зависит от количества спонсоров. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Посмотрим на среднее значение числовых признаков"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data.pivot_table(['backers', 'usd_pledged_real', 'usd_goal_real'], ['state'], aggfunc='mean')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Интересное наблюдение. Средняя запрашиваемая сумма у проваленных проектов почти в 7 раз больше, чем у успешных. Чтобы проект стал успешным, нужно быть скромнее :) Хотя это может говорить о том, что собрать меньшую сумму денег гораздо проще."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Посмотрим на категориальные признаки*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "cat = ['category', 'main_category', 'currency', 'country', 'state']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for c in cat:\n",
    "    print('\\nДанные по категориальному признаку {}'.format(c))\n",
    "    print(data[c].value_counts())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Заметно, что в США запущено подавляющее число проектов, следовательно преобладающая валюта - американский доллар. В признаке **country** присутствует значение N,0\" (видимо какая-то ошибка при парсинге данных). Позже попытаемся избавиться от него.\n",
    "\n",
    "Посмотрим на количество проектов по категориям и подкатегориям."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "main_category = data['main_category'].value_counts()\n",
    "main_category.sort_values(ascending=False, inplace=True)\n",
    "plt.figure(figsize=(20, 5))\n",
    "sns.set(font_scale=1.4)\n",
    "ax = sns.barplot(x=main_category.index, y=main_category.values)\n",
    "ax.set_xlabel('Категории', fontsize=20)\n",
    "ax.set_ylabel('Количество проектов', fontsize=20)\n",
    "ax.set_xticklabels(ax.get_xticklabels(), rotation=45)\n",
    "plt.show();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Заметно, что запущенных проектов больше в индустрии развлечений - фильмы, музыка. Судя по всему, часто собирают средства на публикацию авторы книг. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "category = data['category'].value_counts()\n",
    "category.sort_values(ascending=False, inplace=True)\n",
    "plt.figure(figsize=(20, 40))\n",
    "sns.set(font_scale=1.4)\n",
    "ax = sns.barplot(y=category.index, x=category.values)\n",
    "ax.set_xlabel('Количество проектов', fontsize=20)\n",
    "ax.set_ylabel('Подкатегории', fontsize=20)\n",
    "plt.show();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Посмотрим на целевую переменную*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure(figsize=(8, 5))\n",
    "sns.set(font_scale=1.2)\n",
    "ax = sns.countplot(data['state'])\n",
    "ax.set(xlabel='Успешность проекта', ylabel='Количество проектов')\n",
    "plt.show();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "В классах присутствует небольшой дисбаланс. Заметно, что количество проектов, которые не смогли набрать нужную сумму к дедлайну, всё-таки больше. Что логично, не так-то просто заставить людей отдать свои деньги :)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###  Часть 3. Первичный визуальный анализ признаков"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Подробно посмотрим на числовые признаки*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fig, ax = plt.subplots(nrows=3, ncols=1, figsize=(15, 15))\n",
    "\n",
    "ax[0] = sns.boxplot(x=data['backers'], y=data['state'], orient='h', ax=ax[0])\n",
    "ax[0].set_xscale('log')\n",
    "ax[0].set(xlabel='Спонсоры', ylabel='Успешность проекта')\n",
    "ax[0].set_yticklabels(ax[0].get_yticklabels(), rotation=90)\n",
    "\n",
    "ax[1] = sns.boxplot(x=data['usd_goal_real'], y=data['state'], orient='h', ax=ax[1])\n",
    "ax[1].set_xscale('log')\n",
    "ax[1].set(xlabel='Запрошенная сумма', ylabel='Успешность проекта')\n",
    "ax[1].set_yticklabels(ax[1].get_yticklabels(), rotation=90)\n",
    "\n",
    "ax[2] = sns.boxplot(x=data['usd_pledged_real'], y=data['state'], orient='h', ax=ax[2])\n",
    "ax[2].set_xscale('log')\n",
    "ax[2].set(xlabel='Собранная сумма', ylabel='Успешность проекта')\n",
    "ax[2].set_yticklabels(ax[2].get_yticklabels(), rotation=90)\n",
    "\n",
    "plt.show();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Выглядит все более-менее прилично. Заметен широких разброс числовых признаков - например, количество спонсоров у проекта может насчитывать пару сотен тысяч. Посмотрим на некоторые данные, чтобы проверить выбросы."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data[data['backers'] >= 100000]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data[data['usd_goal_real'] <= 0.1].head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data[data['usd_pledged_real'] >= 10000000].head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Похоже на реальные значения, а не выбросы. К примеру, среди проектов собравших больше 10 млн. долларов - знаменитые Pebble и Pebble 2."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Чтобы посмотреть, как числовые признаки связаны друг с другом, построим *pairplot*. Перед этим прологарифмируем признаки."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data['backers_log'] = np.log(data['backers'] + 1)\n",
    "data['usd_goal_log'] = np.log(data['usd_goal_real'] + 1)\n",
    "data['usd_pledged_log'] = np.log(data['usd_pledged_real'] + 1)\n",
    "\n",
    "num_log = ['backers_log', 'usd_goal_log', 'usd_pledged_log', 'state']\n",
    "\n",
    "sns.pairplot(data[num_log], diag_kind='hist', hue='state', size=4)\n",
    "plt.show();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Подробно рассмотрим категориальные признаки*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "cat_success = data[data['state'] == 'successful']['main_category'].value_counts()\n",
    "plt.figure(figsize = (20, 8))\n",
    "sns.set(font_scale=1.4)\n",
    "ax1 = sns.barplot(x=cat_success.index, y=cat_success.values)\n",
    "ax1.set_title('Количество успешных проектов по категориям', fontsize=20)\n",
    "ax1.set_xticklabels(ax1.get_xticklabels(), rotation=45)\n",
    "ax1.set_xlabel('Категории', fontsize=20)\n",
    "ax1.set_ylabel('Количество', fontsize=20)\n",
    "\n",
    "for p in ax1.patches:\n",
    "    x=p.get_bbox().get_points()[:,0]\n",
    "    y=p.get_bbox().get_points()[1,1]\n",
    "    ax1.annotate('{:.0f}'.format(p.get_height()), (x.mean(), y), ha='center', va='bottom', fontsize=14)\n",
    "\n",
    "cat_failed = data[data['state'] == 'failed']['main_category'].value_counts()\n",
    "plt.figure(figsize = (20, 8))\n",
    "ax2 = sns.barplot(x=cat_failed.index, y=cat_failed.values)\n",
    "ax2.set_title('Количество проваленных проектов по категориям', fontsize=20)\n",
    "ax2.set_xticklabels(ax2.get_xticklabels(), rotation=45)\n",
    "ax2.set_xlabel('Категории', fontsize=20)\n",
    "ax2.set_ylabel('Количество', fontsize=20)\n",
    "\n",
    "for p in ax2.patches:\n",
    "    x=p.get_bbox().get_points()[:,0]\n",
    "    y=p.get_bbox().get_points()[1,1]\n",
    "    ax2.annotate('{:.0f}'.format(p.get_height()), (x.mean(), y), ha='center', va='bottom', fontsize=14)\n",
    "\n",
    "plt.show();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Получается занимательная картинка. Видно, что по некоторым категориям количество успешных проектов больше, чем провалившихся. Найдем все такие категории."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "success_to_falied = cat_success / cat_failed\n",
    "success_to_falied.sort_values(ascending=False, inplace=True)\n",
    "plt.figure(figsize = (20, 8))\n",
    "ax = sns.barplot(x=success_to_falied.index, y=success_to_falied.values)\n",
    "ax.set_title('Отношение успешных проектов к неуспешным по категориям', fontsize=20)\n",
    "ax.set_xlabel('Категории', fontsize=20)\n",
    "ax.set_xticklabels(ax.get_xticklabels(), rotation=45)\n",
    "plt.show();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Получили, что в четырех категориях (танцы, театр, комиксы, музыка) успешных проектов больше, чем провальных. Для музыки это достаточно удивительно, если учитывать, что проектов в данной категории очень много."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "Приведем признаки **deadline** и **launched** к дата-формату и построим признаки от времени. А также приведем целевой признак **state** к числовому формату."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data['deadline'] = pd.to_datetime(data['deadline'])\n",
    "data['launched'] = pd.to_datetime(data['launched'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data['launch_year'] = data['launched'].dt.year\n",
    "data['launch_month'] = data['launched'].dt.month\n",
    "data['launch_day'] = data['launched'].dt.day\n",
    "data['launch_dw'] = data['launched'].dt.dayofweek\n",
    "data['launch_hour'] = data['launched'].dt.hour\n",
    "\n",
    "data['deadline_year'] = data['deadline'].dt.year\n",
    "data['deadline_month'] = data['deadline'].dt.month"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "state_int = {'failed' : 0, 'successful' : 1}\n",
    "data['state'] = data['state'].map(state_int)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Посмотрим как зависит количество запущенных проектов от года и от месяца."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure(figsize=(20, 5))\n",
    "pivot = data.pivot_table(columns=data['launch_year'], values='state', aggfunc='count')\n",
    "ax1 = sns.barplot(pivot.columns.values, pivot.values[0])\n",
    "plt.xlabel('Год')\n",
    "plt.ylabel('Количество проектов')\n",
    "plt.title('Количество проектов по годам', fontsize=20)\n",
    "\n",
    "plt.figure(figsize=(20, 5))\n",
    "pivot = data.pivot_table(columns=data['launch_month'], values='state', aggfunc='count')\n",
    "ax2 = sns.barplot(pivot.columns.values, pivot.values[0])\n",
    "plt.xlabel('Месяц')\n",
    "plt.ylabel('Количество проектов')\n",
    "plt.title('Количество проектов по месяцам', fontsize=20)\n",
    "plt.show();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Заметно, что проекты стараются не запускать в декабре, по всей видимости сказывается новогодний и рождественский ажиотаж, поэтому есть риск, что проект не наберет достаточное количество спонсоров.\n",
    "\n",
    "Подробнее посмотрим на временные признаки."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "heat = data.groupby(['launch_year', 'launch_month']).size().unstack()\n",
    "plt.figure(figsize=(15, 15))\n",
    "ax = sns.heatmap(heat, annot=True, fmt=\".0f\", cmap=\"viridis\", linewidths=.5)\n",
    "ax.set_title('Количество запущенных проектов в зависимости от года/месяца', fontsize=20)\n",
    "ax.set_xlabel('Месяц', fontsize=20)\n",
    "ax.set_ylabel('Год', fontsize=20)\n",
    "ax.set_yticklabels(ax.get_yticklabels(), rotation=0)\n",
    "plt.show();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Как и было сказано, в январе количество проектов падает. Видно что поначалу кикстартер разгонялся и первые три года количество проектов в месяц не превышало 2 тысяч. В глаза бросается июль 2014 года, что-то интересное произошло, от чего количество запущенных проектов выросло в два раза. Вполне возможно, что кикстартер запустили в новых странах. Сделаем такую же картинку, но для успешных проектов."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "heat = data.groupby(['launch_year', 'launch_month'])['state'].sum().unstack()\n",
    "plt.figure(figsize=(15, 15))\n",
    "ax = sns.heatmap(heat, annot=True, fmt=\".0f\", cmap=\"viridis\", linewidths=.5)\n",
    "ax.set_title('Количество успешных проектов в зависимости от года/месяца', fontsize=20)\n",
    "ax.set_xlabel('Месяц', fontsize=20)\n",
    "ax.set_ylabel('Год', fontsize=20)\n",
    "ax.set_yticklabels(ax.get_yticklabels(), rotation=0)\n",
    "plt.show();"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "heat = data.groupby(['launch_month', 'launch_dw'])['state'].sum().unstack()\n",
    "plt.figure(figsize=(15, 15))\n",
    "ax = sns.heatmap(heat, annot=True, fmt=\".0f\", cmap=\"viridis\", linewidths=.5)\n",
    "ax.set_title('Количество успешных проектов в зависимости от месяца/дня недели', fontsize=20)\n",
    "ax.set_xlabel('День недели', fontsize=20)\n",
    "ax.set_ylabel('Месяц', fontsize=20)\n",
    "ax.set_yticklabels(ax.get_yticklabels(), rotation=0)\n",
    "plt.show();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Хорошо заметно, что в выходные количество проектов падает. Тогда как самый пик - вторник, а дальше уже идет на убыль. Возьмем сей факт на вооружение при построении новых признаков. По вторнику заметно, что летом количество успешных проектов немного проседает."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "heat = data.groupby(['launch_hour', 'launch_dw'])['state'].sum().unstack()\n",
    "plt.figure(figsize=(15, 20))\n",
    "ax = sns.heatmap(heat, annot=True, fmt=\".0f\", cmap=\"viridis\", linewidths=.5)\n",
    "ax.set_title('Количество успешных проектов в зависимости от дня недели/часа', fontsize=20)\n",
    "ax.set_xlabel('День недели', fontsize=20)\n",
    "ax.set_ylabel('Час', fontsize=20)\n",
    "ax.set_yticklabels(ax.get_yticklabels(), rotation=0)\n",
    "plt.show();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Очень хорошо заметен промежуток с 6 утра до 12 дня, когда количество проектов проседает. Начиная с 17 до 19 в понедельник-среду самый пик запуска проектов, к концу недели количество проектов заметно снижается. Вывод такой, если хочешь запустить успешный проект - не выбирай выходные для старта :)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Введем новый признак - продолжительность кампании сбора средств в месяцах. И посмотрим, как влияет длительность сбора на успешность проекта."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data['launch_month_year'] = data['launched'].dt.to_period(\"M\")\n",
    "data['deadline_month_year'] = data['deadline'].dt.to_period(\"M\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data['duration'] = data['deadline_month_year'] - data['launch_month_year']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure(figsize = (15, 10))\n",
    "ax = sns.countplot(x='duration', hue='state', data=data)\n",
    "ax.set_title('Распределение успешных/провалившихся проектов по длительности', fontsize=20)\n",
    "ax.set_xlabel('Продолжительность сбора средств, мес.', fontsize=20)\n",
    "ax.set_ylabel('Количество проектов', fontsize=20)\n",
    "plt.show();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "У проектов со сроком сбора средств меньше одного месяца почти равное соотношение успешных/провалившихся. Тогда как проекты с продолжительностью больше одного месяца, имеют больший шанс провалиться. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###  Часть 4. Закономерности, \"инсайты\", особенности данных"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "Выводы:\n",
    " - числовые признаки имеют широкий разброс значений (обусловлено природой данных)\n",
    " - медиана запрошенной суммы меньше у успешных проектов -> нужно быть скромнее\n",
    " - сумма пожертвований линейно зависит от количества спонсоров, что в принципе очевидно\n",
    " - есть только четыре категории (танцы, театр, комиксы и музыка), где количество успешных проектов больше, чем провалившихся\n",
    " - в декабре количество проектов падает (возможно связано с рождественскими праздниками и новым годом), да и вообще зимой проектов меньше\n",
    " - суббота и воскресенье не лучшее время для запуска проекта (скорее всего от того, что люди обычно заняты в выходные и велик шанс, что проект не увидят)\n",
    " - лучшее время для запуска: вторник с 17 до 18 вечера \n",
    " - среди проектов с длительностью меньше 1 месяца практически равное число успешных и провалившихся проектов\n",
    " - проекты, которые собирают деньги больше 1 месяца имеют больше шансов провалиться (тут связано с тем фактом, что длительный срок бывает у таких проектов, которым требуется собрать большую сумму денег)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###  Часть 5. Выбор метрики и модели"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Решаем задачу бинарной классификации. Есть небольшой дисбаланс в целевой переменной (ответы смещены в сторону класса **failed**). Будем использовать метрику ROC AUC. Данная метрика является довольно распространненой для задач с дисбалансом классов.\n",
    "\n",
    "Дла решение задачи классификации я рассмотрел два классических алгоритма:\n",
    " - случайный лес *RandomForestClassifier* \n",
    " - логиcтическая регрессия *LogisticRegression*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###  Часть 6. Предобработка данных "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Загружаем данные"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data = pd.read_csv('..\\data\\ks-projects-201801.csv')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Раньше было обнаружено, что есть некая страна N,0\". Похоже на ошибку парсинга, либо кикстартер плохо выдает страну по некоторым проектам. Так как у нас есть признак **currency** можно восстановить часть данных. Для евро, к сожалению, это не будет так просто, данная валюта является официальной для 19 стран и из какой именно страны был запущен проект сложно узнать."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "wrong_country = (data['country'] == 'N,0\"')\n",
    "d_country = {'USD':'US', 'GBP':'GB', 'CAD':'CA', 'AUD': 'AU', 'SEK':'SE', 'NZD':'NZ', 'DKK':'DK', 'NOK':'NK', 'CHF':'CH'}\n",
    "data.loc[wrong_country, 'country'] = data.loc[wrong_country, 'currency'].map(d_country)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Из-за такой замены в наборе данных появились пропуски (из-за валюты Евро). Выкинем их и другие пропуски"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data.dropna(inplace=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data.drop(data[(data['state'] == 'canceled') | (data['state'] == 'live') | (data['state'] == 'suspended') | (data['state'] == 'undefined')].index, inplace=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Целевую переменную к числовому типу"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "state_int = {'failed' : 0, 'successful' : 1}\n",
    "data['state'] = data['state'].map(state_int)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Выделим признаки для обучения"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "X = data[['main_category', 'category', 'country', 'currency', 'usd_goal_real']]\n",
    "y = data[['state']]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Теперь преобразуем признаки: скалируем признак **usd_goal_real**; к категориальным признакам применим OHE кодирование"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "scaler = StandardScaler()\n",
    "X_goal_scale = X['usd_goal_real'].values.reshape(-1, 1)\n",
    "X_goal_scaled = scaler.fit_transform(X_goal_scale)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "le = LabelEncoder()\n",
    "\n",
    "X['main_category'] = le.fit_transform(X['main_category'])\n",
    "X['category'] = le.fit_transform(X['category'])\n",
    "X['country'] = le.fit_transform(X['country'])\n",
    "X['currency'] = le.fit_transform(X['currency'])\n",
    "\n",
    "ohe = OneHotEncoder(sparse=False)\n",
    "\n",
    "ohe_mcat = ohe.fit_transform(X.main_category.values.reshape(-1, 1))\n",
    "ohe_cat = ohe.fit_transform(X.category.values.reshape(-1, 1))\n",
    "ohe_country = ohe.fit_transform(X.country.values.reshape(-1, 1))\n",
    "ohe_currency = ohe.fit_transform(X.currency.values.reshape(-1, 1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_transformed = np.hstack((X_goal_scaled, ohe_currency, ohe_mcat, ohe_cat, ohe_country))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Разобьем на обучающую и тестовую выборки"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_train, X_test, y_train, y_test = train_test_split(X_transformed, y, test_size=0.3, random_state=42)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###  Часть 7. Создание новых признаков и описание этого процесса"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "Перед тем, как создавать новые признаки, проверим базовые признаки на моделях с параметрами \"из коробки\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "logit = LogisticRegression(random_state=42, n_jobs=-1).fit(X_train, y_train)\n",
    "y_pred = logit.predict_proba(X_test)[:, 1]\n",
    "print('Logistic Regressor baseline score: %0.3f' % (100 * roc_auc_score(y_test, y_pred)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "forest = RandomForestClassifier(random_state=42, n_jobs=-1).fit(X_train, y_train)\n",
    "y_pred = forest.predict_proba(X_test)[:, 1]\n",
    "print('Random Forest Classifier baseline score: %0.3f' % (100 * roc_auc_score(y_test, y_pred)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Модель логистической регрессии оказалась точнее, чем случайный лес. Добавим новые признаки"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# создадим временные признаки\n",
    "data['deadline'] = pd.to_datetime(data['deadline'])\n",
    "data['launched'] = pd.to_datetime(data['launched'])\n",
    "\n",
    "data['launch_ym'] = (100 * data['launched'].dt.year + data['launched'].dt.month).astype(int)\n",
    "data['is_tuesday'] = (data['launched'].dt.dayofweek == 1).astype(int)\n",
    "\n",
    "data['morning'] = ((data['launched'].dt.hour >= 7) & (data['launched'].dt.hour <= 13)).astype(int)\n",
    "data['day'] = ((data['launched'].dt.hour >= 14) & (data['launched'].dt.hour <= 16)).astype(int)\n",
    "data['eve'] = ((data['launched'].dt.hour >= 17) & (data['launched'].dt.hour <= 21)).astype(int)\n",
    "data['is_launch_time'] = ((data['launched'].dt.dayofweek < 5) \n",
    "                          & (data['launched'].dt.hour >= 15) \n",
    "                          & (data['launched'].dt.hour <= 23)).astype(int)\n",
    "\n",
    "# вычислим длительность сбора средств в днях \n",
    "data['duration_day'] = data['deadline'].dt.to_period(\"D\") - data['launched'].dt.to_period(\"D\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_new_features = data[['duration_day', 'launch_ym', 'day', 'morning', 'eve', 'is_tuesday', 'is_launch_time']]\n",
    "X_new_features_scaled = scaler.fit_transform(X_new_features)\n",
    "X_new_feat = np.hstack((X_transformed, X_new_features_scaled))\n",
    "X_new_feat_train, X_new_feat_test, y_train, y_test = train_test_split(X_new_feat, y, test_size=0.3, random_state=42)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Посмотрим, как влияют новые признаки на точность прогнозирования"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "logit.fit(X_new_feat_train, y_train)\n",
    "y_pred = logit.predict_proba(X_new_feat_test)[:, 1]\n",
    "print('Logistic Regressor score with new features: %0.3f' % (100 * roc_auc_score(y_test, y_pred)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "forest.fit(X_new_feat_train, y_train)\n",
    "y_pred = forest.predict_proba(X_new_feat_test)[:, 1]\n",
    "print('Random Forest Classifier score with new features: %0.3f' % (100 * roc_auc_score(y_test, y_pred)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###  Часть 8. Кросс-валидация, подбор параметров"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Так как в данных у нас есть зависимость от времени, то для корректной кросс-валидации необходимо использовать *TimeSeriesSplit*\n",
    "\n",
    "*Logistic Regression*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "time_split = TimeSeriesSplit(n_splits=10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "c_values = np.array([0.1, 1, 10, 50, 100])\n",
    "logit_grid_searcher = GridSearchCV(estimator=logit, param_grid={'C': c_values}, \n",
    "                                   scoring='roc_auc', n_jobs=-1, cv=time_split, verbose=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "logit_grid_searcher.fit(X_new_feat_train, y_train)\n",
    "print('Best score: %0.3f' % (100 * logit_grid_searcher.best_score_))\n",
    "print('Best parameters: %s' % logit_grid_searcher.best_params_)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "y_pred = logit_grid_searcher.predict_proba(X_new_feat_test)[:, 1]\n",
    "print('Logistic Regressor score after timesplit CV: %0.3f' % (100 * roc_auc_score(y_test, y_pred)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Random Forest Classifier*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "parameters = {'n_estimators' : [10, 20],\n",
    "                  'max_features' : [100],\n",
    "                  'max_depth' : [10, 20]\n",
    "                 }\n",
    "forest_grid_searcher = GridSearchCV(estimator=forest, param_grid=parameters, \n",
    "                                    scoring='roc_auc', n_jobs=-1, cv=time_split, verbose=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "forest_grid_searcher.fit(X_new_feat_train, y_train)\n",
    "print('Best score: %0.3f' % (100 * forest_grid_searcher.best_score_))\n",
    "print('Best parameters: %s'% forest_grid_searcher.best_params_)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "y_pred = forest_grid_searcher.predict_proba(X_new_feat_test)[:, 1]\n",
    "print('Random Forest Classifier score after timesplit CV: %0.3f' % (100 * roc_auc_score(y_test, y_pred)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###  Часть 9. Построение кривых валидации и обучения "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def plot_with_err(x, data, **kwargs):\n",
    "    mu, std = data.mean(1), data.std(1)\n",
    "    lines = plt.plot(x, mu, '-', **kwargs)\n",
    "    plt.fill_between(x, mu - std, mu + std, edgecolor='none',\n",
    "                     facecolor=lines[0].get_color(), alpha=0.2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_sizes = np.linspace(0.05, 1, 10)\n",
    "N_train_logit, learn_train_logit, learn_test_logit = model_selection.learning_curve(logit_grid_searcher.best_estimator_,\n",
    "                                                                                    X_new_feat_train, y_train, \n",
    "                                                                                    train_sizes=train_sizes, cv=time_split,\n",
    "                                                                                    scoring='roc_auc', n_jobs=-1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure(figsize = (10, 5))\n",
    "plot_with_err(N_train_logit, learn_train_logit, label='training scores')\n",
    "plot_with_err(N_train_logit, learn_test_logit, label='validation scores')\n",
    "plt.xlabel('Размер датасета', fontsize=14)\n",
    "plt.ylabel('ROC_AUC', fontsize=14)\n",
    "plt.title('Logistic Regression', fontsize=14)\n",
    "plt.grid(True)\n",
    "plt.legend();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Кривые сходятся, это не очень хорошо. Добавление данных в датасет определенно не пойдет на пользу, точность прогнозирования не повысится. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "N_train_forest, learn_train_forest, learn_test_forest = model_selection.learning_curve(forest_grid_searcher.best_estimator_,\n",
    "                                                  X_new_feat_train, y_train, train_sizes=train_sizes, cv=time_split,\n",
    "                                                  scoring='roc_auc', n_jobs=-1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.figure(figsize = (10, 5))\n",
    "plot_with_err(N_train_forest, learn_train_forest, label='training scores')\n",
    "plot_with_err(N_train_forest, learn_test_forest, label='validation scores')\n",
    "plt.xlabel('Размер датасета', fontsize=14)\n",
    "plt.ylabel('ROC_AUC', fontsize=14)\n",
    "plt.title('Random Forest Classifier', fontsize=14)\n",
    "plt.grid(True)\n",
    "plt.legend();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Схожая картинка. Возможно надо поиграться с признаками, чтобы случайный лес дал лучшую оценку."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "###  Часть 10. Прогноз для тестовой или отложенной выборки"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "y_pred = logit_grid_searcher.predict_proba(X_new_feat_test)[:, 1]\n",
    "print('Logistic Regressor на тестовой выборке: %0.3f' % (100 * roc_auc_score(y_test, y_pred)))\n",
    "y_pred = forest_grid_searcher.predict_proba(X_new_feat_test)[:, 1]\n",
    "print('Random Forest Classifier на тестовой выборке: %0.3f' % (100 * roc_auc_score(y_test, y_pred)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Кросс-валидация позволила модели Random Forest Classifier выдать лучшую оценку."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Часть 11. Выводы "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Построена модель для прогнозирования успешности проекта. Оценка не очень большая получилась, хотелось бы больше :) Возможно не хватает данных - например, подробное описание проекта, количество медиа-контента на странице проекта, количество обновлений страницы проекта во течение кампании сбора средств и т.д. Более аккуратные поиск и создание новых признаков тоже может дать улучшение качества модели. Что еще можно сделать? Конечно же решать задачу многоклассовой классификации :)  "
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
